CloudWatch アラームのダウンタイム(特定期間の発報抑止)を Metric Math を使用して実現してみた

CloudWatch アラームのダウンタイム(特定期間の発報抑止)を Metric Math を使用して実現してみた

特定の時間帯はアラートに引っかかることが予めわかっているので静観したい……というときに。
Clock Icon2021.08.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンバンハ、千葉(幸)です。

CloudWatch アラームを使用して監視・通知を実施している場合に、特定の期間だけはアラート発報を抑止したい、ということがあるかと思います。

手っ取り早く思いつくのは該当の CloudWatch アラームを一時的に無効化するパターンで、外部から CLI やプログラムを利用して定期的にステータスを変更させることでダウンタイムを実現できます。

もしくは、CloudWatch アラーム→ SNS トピックの後段に Lambda 関数を配置し、呼び出された日時が定義済みの静観期間に含まれるようであれば通知を抑止する、というパターンもあるでしょう。

いずれも CloudWatch 外部のリソースが必要となるため、もう少しお手軽に実現したいところです。最近追加された CloudWatch Metric Math 関数の中にダウンタイムの実装に使用できそうなものがあったため、その使い心地を確認してみます。

3 行まとめ

  • 外部のリソースが不要な点は嬉しい
  • ダウンタイムの期間の指定の仕方がちょっと……大変
  • こまめに変更が必要なケースにはマッチしなさそう

使用する Metric Math 関数

ダウンタイムの実装に使用できそうな、タイムスタンプを基に戻り値を返してくれる関数は以下の通りです。

関数 概要
MINUTE 元の時系列の各タイムスタンプの分(UTC)を表す0から59までの整数を返す
HOUR 元の時系列の各タイムスタンプの時間(UTC)を表す0から23までの整数を返す
DAY 元の時系列の各タイムスタンプの曜日(UTC)を表す1から7までの整数のを返す。1は月曜日、7は日曜日を表す
DATE 元の時系列の各タイムスタンプの日(UTC)を表す1から31までの整数を返す
MONTH 元の時系列の各タイムスタンプの月(UTC)を表す1から12までの整数を返す

これらの関数は IF 関数と組み合わせての使用が想定されています。

IF 関数

IF 関数は以下の書式で使用します。

IF(条件 , trueの場合の値 , falseの場合の値)

falseの場合の値は省略できます。

また、以下の演算子を使用できます。

演算子のタイプ サポートされている演算子
比較演算子 == , != , <= , >= , < , >
論理演算子 AND または && , OR または ||

以下のように()をネストすることもできます。

IF( (条件1) OR (条件2) , trueの場合の値)

タイムスタンプを基にする関数と組み合わせる場合には、以下のように使用します。

IF(HOUR(m1) < 13 , m1)

ここでのm1は時系列のメトリクスを表すものであり、上記の条件式は「メトリクスのタイムスタンプの時間(UTC)が 0~12 であればそのままメトリクスを返し、それ以外であれば何も返さない」という挙動になります。

IF 関数についての詳細は以下をご参照ください。

Metric Math の確認

まずは条件式の正しい書き方を確認するために、定常的に値がパブリッシュされているメトリクスを例に取ります。条件式を適用し、意図した通り特定期間のグラフの描画が変化するかを確認します。

今回は以下のメトリクスを用いて試します。

MetricsMath_IF-8082245

常に一定のメトリクスが発行されています。なお、ここでは JST で描画しています。

土日をダウンタイムにする場合

分かりやすく「土日(JST)は丸々ダウンタイムにしたい」というケースです。今回使用する Metrics Math 関数はいずれも UTC 基準のため、JST から変換する必要があります。

抑止したい箇所の曜日をまたいでの指定はできないため、以下を OR で繋いであげます。

  • 金曜日の 15時 - 23時台(DAY(m1)==5 AND (15<=HOUR(m1) AND HOUR(m1)<=23)
  • 土曜日(DAY(m1)==6
  • 日曜日の 0時 - 14時台(DAY(m1)==7 AND (0<=HOUR(m1) AND HOUR(m1)<=14)

実際に繋いだものが以下です。なんかこう……ワクワクしてきますね。

IF((DAY(m1)==5 AND (15<=HOUR(m1) AND HOUR(m1)<=23)) OR DAY(m1)==6 OR (DAY(m1)==7 AND (0<=HOUR(m1) AND HOUR(m1)<=14)),0,m1)

適用してみると、意図通り JST での土曜、日曜の期間はメトリクスが 0 になりました。

MetricMath_Downtime

MINUTE を指定する場合

「日次で 10:30-20:30(JST)だけ監視対象としたい」というケースを考えます。

UTC に変換すれば 01:30-11:30 です。MINUTE での指定が必要な時間帯は時間をまたいでの指定ができないため、分割する必要があります。

以下を OR 条件でつなぎます。

  • 1 時台(HOUR(m1)==1 AND MINUTE(m1)>30
  • 2 時〜 10 時台(2<=HOUR(m1) AND HOUR(m1)<=10
  • 11 時台(HOUR(m1)==11 AND MINUTE(m1)<30

繋げたものが以下です。なんかこう……ワクワクしてきますね。

IF((HOUR(m1)==1 AND MINUTE(m1)>30) OR (2<=HOUR(m1) AND HOUR(m1)<=10) OR (HOUR(m1)==11 AND MINUTE(m1)<30) ,m1,0)

適用すると以下のようになります。

MetricMath_Minute

なお、falseの場合の値を省略すればダウンタイム時の値が0でなくnullになります。

IF((HOUR(m1)==1 AND MINUTE(m1)>30) OR (2<=HOUR(m1) AND HOUR(m1)<=10) OR (HOUR(m1)==11 AND MINUTE(m1)<30) ,m1)

MetricMath_null

値が欠損するよりは0を発行しておく方がよいでしょう。

ここまで見てきた曜日指定と MINUTE 指定が組み合わさると、条件式の書き方が大変なことになりそうですね、、、

CloudWatch アラームとの組み合わせ

Metric Math と CloudWatch アラームを組み合わせて、ダウンタイムに発報されないことを確認します。

今回はサンプルのメトリクスを手動で発行し、それに対してアラームをセットします。

aws cloudwatch put-metric-data\
 --namespace Sample\
 --metric-name TestMetric\
 --value 1

このように手で叩いた時だけカウントされています。

MetricSample

CloudWatch アラームの作成

まずは条件式をセットします。「数式」から「空の式で始まる」を選択します。

metricMath_add

先ほどの MINUTE を使用する例の条件式を入力します。「10:30-20:30(UTC)」以外の時間はメトリクスが 0 に上書きされます。

IF((HOUR(m1)==1 AND MINUTE(m1)>30) OR (2<=HOUR(m1) AND HOUR(m1)<=10) OR (HOUR(m1)==11 AND MINUTE(m1)<30) ,m1,0)

MetricMath_IF

ベルマークのボタンを押下して CloudWatch アラームを作成します。今回は比較のため、基のメトリクスと Metric Math の計算後のグラフそれぞれで作成します。

MetricMath_alarm

以下の通り作成しました。1回でも 0 より大きくなった場合にアラーム状態に遷移する条件です。

CloudWatchAlarm

↑ Metric Math をベースにしている方は0が発行され続けているため OK 状態ですが、基のメトリクスは手動で発行しない限りデータが無い状態です。

ダウンタイム中の静観の確認

ここで再度メトリクスを発行します。発行したのは 09:40(JST)頃です。

aws cloudwatch put-metric-data\
 --namespace Sample\
 --metric-name TestMetric\
 --value 1

基のメトリクスの方だけがアラーム状態に遷移しました。ダウンタイムの設定が正常に効いていることが分かります。

CloudWatch_Alarm-state

ダウンタイム外の発報の確認

CloudWatch アラーム上で以下のように数式を修正し、09:30-20:30を監視対象とするようにしてみます。

IF((HOUR(m1)==0 AND MINUTE(m1)>30) OR (1<=HOUR(m1) AND HOUR(m1)<=10) OR (HOUR(m1)==11 AND MINUTE(m1)<30) ,m1,0)

変更手順を軽く押さえておきましょう。

CloudWatch アラームの変更画面からメトリクスの「編集」を押下します。

Modify_Alarm

グラフを編集できる画面に遷移するため、新たな条件式に修正し、「メトリクスの選択」を押下します。

ModifyMetric

その後、元のアラームの変更画面に戻るため、「アラームの変更」を確定させれば修正は完了です。

再度 CLI でメトリクスの発行を実行します。今回は 09:50 ごろの実行です。

aws cloudwatch put-metric-data\
 --namespace Sample\
 --metric-name TestMetric\
 --value 1

メトリクスが記録された時間がダウンタイムに含まれていないため、どちらのアラームでもアラーム状態に遷移しました。

CloudWatch_Alarm

期待した通りの挙動です!

終わりに

Metric Math による監視抑止の仕組みを試してみました。

別に Lamnda 関数などを用意する必要がなく、CloudWatch だけで完結できるのはお手軽で嬉しいです。意図せず Lambda 関数が正常に起動しなかった、という事象も避けられるのもポイントが高いです。

一方で、ダウンタイムの指定の仕方がかなり……ワクワクする感じです。条件が細かくなるとそのぶん条件式が長くなりそうで、そこのハードルは高い印象です。そういった意味で、頻繁に時刻変更のメンテナンスが必要なケースにはマッチしないと考えました。

方式によりメリデメあるかと思いますので、選択肢の一つとして覚えておいていただければ嬉しいです。

以上、 チバユキ (@batchicchi) がお送りしました。

関連

CloudWatch アラームを一時的に無効化することで発報抑止するパターンです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.